home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / arcers / tar316.zip / TAPE.C < prev    next >
Text File  |  1994-07-21  |  16KB  |  661 lines

  1. /* tape.c - handle (tape) archive for the Tar program (see file tar.c)
  2.  * Author: T.V.Shaporev
  3.  * Creation date: 14 Dec 1990
  4.  * Contains both MS-DOS and UNIX specific codes
  5.  * Called by many functions - see files tar.c store.c extract.c
  6.  */
  7. #include <stdio.h>
  8. #include <errno.h>
  9.  
  10. #include "sysup.h"
  11. #include "modern.h"
  12. #include "zippipe.h"
  13. #include "lzwhead.h"
  14. #include "compress.h"
  15. #include "define.h"
  16.  
  17. #ifdef MODERN
  18. #    include <string.h>
  19. #    include <stdlib.h>
  20. #else
  21. #    ifdef M_XENIX
  22. #        include <string.h>
  23. #    else
  24.         int strlen();
  25.         char *strcpy(), *strncpy(), *mktemp();
  26. #    endif
  27.     extern char *sys_errlist[];
  28.     extern int sys_nerr;
  29. #endif
  30. #ifdef MSDOS
  31. #    include <io.h>
  32. #    ifdef __TURBOC__
  33. #        include <dir.h>
  34. #    else
  35. #        include <direct.h>
  36. #    endif
  37. #else
  38.     int  creat(), open(), read(), write(), close();
  39.     long lseek();
  40. #endif
  41.  
  42. static int n_read, mblock, nblock, rblock, wblock;
  43. static int indread, indwrite;
  44. static char rerror[] = "Tar: tape read error\n";
  45.  
  46. static int  sread  __ARGS__((char*, int));
  47. static int  swrite __ARGS__((char*, int));
  48. static int  sback  __ARGS__((int));
  49. #ifdef MSDOS
  50. extern int  dread  __ARGS__((char*, int));
  51. extern int  dwrite __ARGS__((char*, int));
  52. extern int  dback  __ARGS__((int));
  53.  
  54. extern int  qparse __ARGS__((char*));
  55. extern int  qbegin __ARGS__((void));
  56. extern int  qread  __ARGS__((char*, int));
  57. extern int  qwrite __ARGS__((char*, int));
  58. extern int  qback  __ARGS__((int));
  59. #endif
  60. static void talign __ARGS__((long));
  61.  
  62. void printbs __ARGS__((int));
  63.  
  64. static void psyserr __ARGS__((void))
  65. {
  66.    if (errno < sys_nerr) (void)fprintf(myout, "%s\n", sys_errlist[errno]);
  67.    else                  (void)fprintf(myout, "error %d\n", errno);
  68. }
  69.  
  70. static int sread(buf, n) /* regular file reading */
  71. char *buf; register n;
  72. {
  73.    if ((n = read(handle, buf, n)) == -1) {
  74.       (void)fprintf(myout, "Tar: archive read error: "); psyserr();
  75.    }
  76.    return n;
  77. }
  78.  
  79. static int swrite(buf, n) /* regular file writing */
  80. char *buf; register n;
  81. {
  82.    if (write(hwrite, buf, n) != n) {
  83.       (void)fprintf(myout, "Tar: archive write error: ");
  84. #ifdef MSDOS
  85.       if (n != -1) (void)fprintf(myout,"disk full\n"); else
  86. #endif
  87.       psyserr();
  88.       n = -1;
  89.    }
  90.    return n;
  91. }
  92.  
  93. static int sback(n)
  94. register n;
  95. {
  96.    return lseek(handle, (long)-BLKSIZE*n, 1) < 0 ? -1 : n;
  97. }
  98.  
  99. #ifdef USE_COMPRESS
  100. static int zwrite __ARGS__((char*, int));
  101.  
  102. static int zwrite(buf, n) /* compressed file writing */
  103. char *buf; register n;
  104. {
  105.    cpiece(buf, n); return n;
  106. }
  107. #endif
  108.  
  109. static int gread  __ARGS__((char*, int));
  110. static int gwrite __ARGS__((char*, int));
  111.  
  112. static int gread(buf, n) /* deflated file reading */
  113. char *buf; register n;
  114. {
  115.    if ((n = unzread(buf, n)) == -1) {
  116.       (void)fprintf(myout, "Tar: unzip error: %s\n", ziperrlist[ziperror]);
  117.    }
  118.    return n;
  119. }
  120.  
  121. static int gwrite(buf, n) /* deflated file reading */
  122. char *buf; register n;
  123. {
  124.    if ((n = zipwrite(buf, n)) == -1) {
  125.       (void)fprintf(myout, "Tar: unzip error: %s\n", ziperrlist[ziperror]);
  126.    }
  127.    return n;
  128. }
  129.  
  130. static int ziperr __ARGS__((void))
  131. {
  132.    (void)fprintf(stderr, "Tar: zip error: %s\n", ziperrlist[ziperror]);
  133.    return ziperror == ZNOMEM ? ESMALL : ERINIT;
  134. }
  135.  
  136. #ifndef USE_COMPRESS
  137. static int twofault __ARGS__((char*, int));
  138.  
  139. /*ARGSUSED2*/ static int twofault(buf, n)
  140. char *buf; register n;
  141. {
  142. #ifdef __TURBOC__
  143.    (void)buf; (void)n;
  144. #endif
  145.    return -1;
  146. }
  147. #endif
  148.  
  149. /*ARGSUSED*/ static int onefault(n)
  150. int n;
  151. {
  152. #ifdef __TURBOC__
  153.    (void)n;
  154. #endif
  155.    return -1;
  156. }
  157.  
  158. static int (*pread) __ARGS__((char*, int)) = sread;
  159. static int (*pwrite)__ARGS__((char*, int)) = swrite;
  160. static int (*pback) __ARGS__((int))        = sback;
  161.  
  162. static int (*lread) __ARGS__((char*, int)) = sread;
  163. static int (*lwrite)__ARGS__((char*, int)) = swrite;
  164. static int (*lback) __ARGS__((int))        = sback;
  165. static int (*rcount)__ARGS__((char*, int)) = sread;
  166.  
  167. static int cntread  __ARGS__((char*, int));
  168.  
  169. static int cntread(buf, n)
  170. char *buf; register n;
  171. {
  172.    if ((n = (*rcount)(buf, n)) != -1) {
  173.       allblock += (BLKSIZE-1 + (unsigned)n) / BLKSIZE;
  174.    }
  175.    return n;
  176. }
  177.  
  178. static void talign(i)
  179. long i;
  180. {
  181.    if (i % BLKSIZE) {
  182.       (void)fprintf(myout, "Tar: tape blocksize error\n");
  183.       if (!i_flag) done(ERREAD);
  184.    }
  185. }
  186.  
  187. void printbs(bs)
  188. int bs;
  189. {
  190.    if (v_flag) (void)fprintf(myout, "Tar: blocksize = %d\n", bs);
  191. }
  192.  
  193. static void wrerror __ARGS__((void))
  194. {
  195.    (void)fprintf(myout, "Tar: tape write error\n");
  196.    done(EWRITE);
  197. }
  198.  
  199. static int indget;
  200. static int eof_already = FALSE;
  201. static int got_length;
  202. static int indput;
  203.  
  204. static int getbyte __ARGS__(( void ))
  205. {
  206.    if (eof_already) goto end;
  207.    if (indget >= got_length) {
  208.       if (pksize == 0) {
  209.          if ((got_length = (*lread)(pk_inp, MAXBLOCK*BLKSIZE)) < 0) goto err;
  210.          if ((sa.st_mode & S_IFMT) == S_IFCHR) talign((long)got_length);
  211.          pksize = got_length;
  212.          if (pksize && (pksize % BLKSIZE)==0) printbs(pksize/BLKSIZE);
  213.       } else {
  214.          if (got_length < pksize || got_length % BLKSIZE) goto end;
  215.          if ((got_length = (*lread)(pk_inp, pksize)) < 0) goto err;
  216.       }
  217.       if (got_length < 1) goto end;
  218.       indget = 0;
  219.    }
  220.    return ((unsigned char *)pk_inp)[indget++];
  221. err:
  222.    (void)fprintf(myout, rerror);
  223.    done(ERREAD);
  224. end:
  225.    eof_already = TRUE;
  226.    return EOF;
  227. }
  228.  
  229. static void pkflush __ARGS__((void))
  230. {
  231. #ifdef MSDOS
  232.    if (devtype != DEV_FILE && devtype != DEV_FLOP)
  233. #else
  234.    if (!isfile)
  235. #endif
  236.       while (indput < pksize) pk_out[indput++] = 0;
  237.  
  238.    if ((*lwrite)(pk_out, indput) < indput) wrerror();
  239.    indput = 0;
  240. }
  241.  
  242. static void putbyte(c)
  243. register c;
  244. {
  245.    if (indput >= pksize) {
  246. #ifndef pksize
  247.       /* Buffer size must not be less then 512 bytes, so we */
  248.       /* can wait for blocksize will be detected by reading */
  249.       if (indput < BLKSIZE) goto put;
  250.       if (pksize < BLKSIZE) pksize = BLKSIZE;
  251. #endif
  252.       pkflush();
  253.    }
  254. put:
  255.    pk_out[indput++] = c;
  256. }
  257.  
  258. int initape(name)
  259. char *name;
  260. {
  261. #ifdef UNIX
  262.    char tn[10]; register char *n;
  263. #endif
  264. #ifdef MSDOS
  265.    register k;
  266. #endif
  267.  
  268.    handle = -1;
  269.  
  270.    pread  = lread  = sread;
  271.    pwrite = lwrite = swrite;
  272.    pback  = lback  = sback;
  273.  
  274.    if (name && name[0]=='-' && name[1]==0) {
  275.       if ((a_flag && !c_flag) || d_flag) {
  276.          (void)fprintf(stderr, "Tar: can\'t update stdout\n");
  277.          return ERRARG;
  278.       }
  279. #ifdef myinp
  280.       if (j_flag
  281. #  ifndef MSDOS
  282.           || w_flag
  283. #  endif
  284.          ) {
  285.          (void)fprintf(stderr, "Tar: input must be free\n");
  286.          return ERRARG;
  287.       }
  288. #endif
  289.       handle = a_flag ? /* stdout */ 1 : /* stdin */ 0;
  290.       myout  = stderr;
  291.    } else {
  292. #ifdef UNIX
  293.       if (name && name[0]) {
  294.          n = name;
  295.       } else {
  296.          n = strcpy(tn, "/dev/mt0"); tn[7] = (ndrive & 7) | '0';
  297.       }
  298.       handle = c_flag ? creat(n, 0666) :
  299.                         open (n, a_flag && !d_flag ? O_RDWR : O_RDONLY);
  300.       if (handle < 0) {
  301.          cantopen(n); return ERINIT;
  302.       }
  303. #endif
  304.  
  305. #ifdef MSDOS
  306.       if (!name || !name[0]) {
  307.          devtype = DEV_FLOP;
  308.      inidisk();
  309.       } else if ((k=qparse(name)) != FALSE) {
  310.          if (k != TRUE) return ERRARG;
  311.          pread   = lread  = qread;
  312.          pwrite  = lwrite = qwrite;
  313.          pback   = lback  = qback;
  314.          devtype = DEV_QIC2;
  315.       } else {
  316.          if (!k_flag && defdev(name)==0) k_flag = TRUE;
  317.          if (k_flag) {
  318.             devtype = DEV_FLOP;
  319.         inidisk();
  320.          } else {
  321.             handle = open(name, !a_flag || d_flag ? O_RDONLY+O_BINARY :
  322.                                  c_flag ? O_CREAT+O_TRUNC+O_WRONLY+O_BINARY :
  323.                                           O_RDWR+O_BINARY,
  324.                                 S_IREAD+S_IWRITE);
  325.             if (handle < 0) {
  326.                cantopen(name); return ERINIT;
  327.             }
  328.             devtype = DEV_FILE;
  329.          }
  330.       }
  331.       if (devtype == DEV_FLOP) {
  332.          pread  = lread  = dread;
  333.          pwrite = lwrite = dwrite;
  334.          pback  = lback  = dback;
  335.       }
  336. #endif
  337.    }
  338.    if (t_flag) {/* yet another redirection */
  339.       rcount = lread; pread = lread = cntread; allblock = 0L;
  340.    }
  341.    if (!cblock & c_flag) printbs(cblock = MAXBLOCK);
  342.    if (handle < 0 || fstat(handle, &sa) != 0) sa.st_mode = S_IFBLK;
  343.    hwrite = handle;
  344.    n_read = 0;
  345.    return CORRECT;
  346. }
  347.  
  348. static void swapbufs __ARGS__((void))
  349. {
  350.    register j; register char *p;
  351.  
  352.    p = pk_inp; pk_inp = io_buf; io_buf = p;
  353.    p = pk_out; pk_out = io_2nd; io_2nd = p;
  354.  
  355.    j = pksize;
  356.    pksize = BLKSIZE*cblock;
  357.    cblock = j/BLKSIZE;
  358. }
  359.  
  360. int redirect()
  361. {
  362.    if (pktype == PKpLZW) {
  363.       /* Redirect IO */
  364.       pread  = dpiece;
  365. #ifdef USE_COMPRESS
  366.       pwrite = zwrite;
  367. #else
  368.       pwrite = twofault;
  369. #endif
  370.       pback  = onefault;
  371.  
  372.       swapbufs();
  373.  
  374.       if (x_flag || t_flag || d_flag) {
  375.          register j;
  376.  
  377.          indget = 0; got_length = (int)n_read;
  378.          if ((j=dbegin(getbyte))!=0) {
  379.             if (j < 0) {
  380.                outmem(stderr);
  381.                return ESMALL;
  382.             } else {
  383.                (void)fprintf(stderr,
  384.                   "Tar: archive is not in compressed format\n");
  385.                return ERINIT;
  386.             }
  387.          }
  388.       }
  389.       if (a_flag || d_flag) {
  390. #ifdef USE_COMPRESS
  391.          if (cbegin(pklevel, putbyte, 0x7fffffffL) != pklevel) {
  392.             outmem(stderr);
  393.             return ESMALL;
  394.          }
  395. #else
  396.          (void)fprintf(stderr,
  397.          "Tar: this restricted version does not support LZW compression\n");
  398.          return ERRARG;
  399. #endif
  400.       }
  401. #ifdef USE_COMPRESS
  402.       indput = 0;
  403. #endif
  404.    } else if (pktype == PKZIP) {
  405.       /* Redirect IO */
  406.       pread = gread; pwrite = gwrite; pback = onefault;
  407.       swapbufs();
  408.  
  409.       if (x_flag || t_flag || d_flag) {
  410.          indget = 0; got_length = (int)n_read;
  411.          if (unzopen(getbyte, ZIP_ANY) != 0) return ziperr();
  412.       }
  413.       indput = 0;
  414.       if (a_flag || d_flag) {
  415.          if (zipcreat(putbyte, ZIP_PKW, pklevel) != 0) return ziperr();
  416.       }
  417.    }
  418.    rblock = mblock = cblock;
  419.    nblock = 0;
  420.    return CORRECT;
  421. }
  422.  
  423. int runtape()
  424. {
  425.    register k;
  426. #ifdef MSDOS
  427.    if (devtype == DEV_QIC2) {
  428.       if (qbegin()) return ERINIT;
  429.    }
  430. #endif
  431.    if ((k = redirect()) != CORRECT) return k;
  432.    if (c_flag && !mblock) printbs(cblock = mblock = MAXBLOCK);
  433.    wblock = 0;
  434.    return CORRECT;
  435. }
  436.  
  437. void duptape(n)
  438. char *n;
  439. {
  440.    register i;
  441.    static char template[] = "XXXXXX";
  442.  
  443.    io_2nd = getbuf(BLKSIZE * (mblock ? mblock : MAXBLOCK));
  444.    if (!io_2nd) done(ESMALL);
  445.  
  446.    i=strlen(n);
  447.    while (i>0 &&
  448. #ifdef MSDOS
  449.                  n[i-1]!='\\' && n[i-1]!=':' &&
  450. #endif
  451.                                                 n[i-1]!='/') --i;
  452.    scratch = salloc((int)(i + sizeof(template)));
  453.    (void)strncpy(scratch, n, i);
  454.    (void)strcpy (scratch+i, template);
  455.    (void)mktemp (scratch);
  456. #ifdef UNIX
  457.    hwrite = creat(scratch, 0666);
  458. #endif
  459. #ifdef MSDOS
  460.    hwrite = open(scratch, O_CREAT+O_TRUNC+O_RDWR+O_BINARY, S_IREAD+S_IWRITE);
  461. #endif
  462.    if (hwrite < 0) {
  463.       (void)fprintf(myout, "Tar: can\'t create scratch file\n");
  464.       done(EWRITE);
  465.    }
  466. }
  467.  
  468. void backtape()
  469. {
  470.    register i;
  471.  
  472.    talign((long)n_read);
  473.    if ((i = (int)(n_read / BLKSIZE % mblock)) == 0) i = mblock;
  474.    if (!isfile) {
  475.       register j;
  476.  
  477.       if ((*pback)(i)!=i) goto fault;
  478.       if ((j=(*pread)(io_buf, BLKSIZE*rblock))<BLKSIZE) goto fault;
  479.       n_read += j;
  480.    }
  481.    if ((*pback)(i) != i) goto fault;
  482.    wblock = --rblock; indread = indwrite = 0;
  483.    return;
  484. fault:
  485.    (void)fprintf(myout, "Tar: tape seek fault\n");
  486.    done(ERREAD);
  487. }
  488.  
  489. void endtape()
  490. {
  491.    nullblock(steptape());
  492.    if (wblock) {
  493.       if ((*pwrite)(io_2nd, BLKSIZE*((
  494. #ifdef MSDOS
  495.                      devtype == DEV_FILE || devtype == DEV_FLOP
  496. #else
  497.                      isfile
  498. #endif
  499. #ifdef USE_COMPRESS
  500.                      || pwrite == zwrite
  501. #endif
  502.                      || pwrite == gwrite)
  503.                      && wblock < mblock ? wblock : mblock)) < 0) {
  504.          wrerror();
  505.       }
  506.    }
  507. #ifdef USE_COMPRESS
  508.    if (pwrite == zwrite) {/* compression on output */
  509.       if (cflush() < 0) wrerror();
  510.       if (indput > 0) pkflush();
  511.    } else
  512. #endif
  513.    if (pwrite == gwrite) {/* zip compression */
  514.       if (zipclose() == -1L) wrerror();
  515.       if (indput > 0) pkflush();
  516.    }
  517.    if (hwrite >= 0 && close(hwrite)!=0) {
  518.       (void)fprintf(myout, "Tar: tape close error\n");
  519.       done(EWRITE);
  520.    }
  521. }
  522.  
  523. static int readbuf __ARGS__(( void ))
  524. {
  525.    register i;
  526.  
  527.    for (;;) {
  528.       if (mblock) {
  529.          if ((i=(*pread)(io_buf, BLKSIZE*mblock)) < BLKSIZE || i%BLKSIZE!=0) {
  530.             (void)fprintf(myout, rerror);
  531.             if (i_flag) return -1;
  532.             done(ERREAD);
  533.          }
  534.          n_read += i;
  535.          nblock = i / BLKSIZE;
  536.       } else {
  537.          if ((i = (*pread)(io_buf, MAXBLOCK*BLKSIZE)) < 1) {
  538.             (void)fprintf(myout, rerror);
  539.             if (i_flag) return -1;
  540.             done(ERREAD);
  541.          }
  542.          n_read += i;
  543.          if (i % BLKSIZE != 0 && pktest((unsigned char*)io_buf) == CORRECT) {
  544.             mblock = cblock; n_read = 0; continue;
  545.          }
  546.          talign((long)i);
  547.          mblock = nblock = i / BLKSIZE;
  548.          printbs(cblock = mblock);
  549.       }
  550.       break;
  551.    }
  552.    rblock = 0;
  553.    return 0;
  554. }
  555.  
  556. header *readtape()
  557. {
  558.    if (rblock>=nblock && readbuf()!=0) return NULL;
  559.    indread = 0;
  560.    return (header *)(io_buf + BLKSIZE * rblock++);
  561. }
  562.  
  563. int readbyte()
  564. {
  565.    register c;
  566.  
  567.    if (indread == 0) ++rblock; /* get 1-st byte - take all the block */
  568.    if (rblock>nblock) {
  569.       if (readbuf()!=0) return -1;
  570.       rblock = 1; /* preserve 1-st block from readtape() */
  571.    }
  572.    c = ((unsigned char *)(io_buf + BLKSIZE * (rblock-1)))[indread];
  573.    indread = (indread+1) & (BLKSIZE-1);
  574.    return c;
  575. }
  576.  
  577. void bacouple()
  578. /* return to the beginning of block after try to uncompress */
  579. {
  580.    indread = 0; --rblock;
  581. }
  582.  
  583. int readarch(h, length)
  584. int h; long length;
  585. {
  586.    register i;
  587.  
  588.    while (length > 0) {
  589.       if (rblock>=nblock && readbuf()!=0) return -1;
  590.       if ((i = (nblock-rblock)*BLKSIZE) > length) i = (int)length;
  591.       if (write(h, io_buf + rblock * BLKSIZE, i)!=i)
  592.          extwrerr();
  593.       rblock += (i + BLKSIZE-1) / BLKSIZE;
  594.       length -= i;
  595.    }
  596.    indread = 0;
  597.    return 0;
  598. }
  599.  
  600. header *steptape()
  601. {
  602.    if (!mblock) mblock = 1;
  603.    if (wblock >= mblock) {
  604.       if ((*pwrite)(io_2nd, BLKSIZE*mblock) < 0) wrerror();
  605.       wblock = 0;
  606.    }
  607.    indwrite = 0;
  608.    return (header *)(io_2nd + BLKSIZE * wblock++);
  609. }
  610.  
  611. void writebyte(c)
  612. int c;
  613. {
  614.    if (indwrite == 0) ++wblock;
  615.    if (wblock > mblock) {
  616.       if ((*pwrite)(io_2nd, BLKSIZE*mblock) < 0) wrerror();
  617.       wblock = 1;
  618.    }
  619.    ((unsigned char *)(io_2nd + BLKSIZE * (wblock-1)))[indwrite] = c;
  620.    indwrite = (indwrite+1) & (BLKSIZE-1);
  621. }
  622.  
  623. int writearch(h, length, name)
  624. int h; long length; char *name;
  625. {
  626.    register i; register j; register k;
  627.    register char *p;
  628.    register b;
  629.  
  630.    if (!mblock) mblock = 1;
  631.  
  632.    b = 0;
  633.    while (length > 0) {
  634.       if (wblock >= mblock) {
  635.          if ((*pwrite)(io_2nd, BLKSIZE*mblock) < 0) wrerror();
  636.          wblock = 0;
  637.       }
  638.       k = BLKSIZE * (mblock-wblock);
  639.       i = length < k ? (int)length : k;
  640.       p = io_2nd + BLKSIZE * wblock;
  641.       if ((j = read(h, p, i)) < 0) {
  642.          (void)fprintf(myout, "Tar: error reading \'%s\'\n", name);
  643.          done(ERREAD);
  644.       }
  645.       /* Calculate number of blocks affected */
  646.       k = (BLKSIZE-1 + j) / BLKSIZE;
  647.       wblock += k;
  648.       b      += k;
  649.       /* Fill the slack area */
  650.       for (p+=j, k=BLKSIZE*k-j; k>0; k--) *p++ = '\0';
  651.       if (j != i) return b;
  652.       length -= i;
  653.    }
  654.    if (wblock >= mblock) {
  655.       if ((*pwrite)(io_2nd, BLKSIZE*mblock) < 0) wrerror();
  656.       wblock = 0;
  657.    }
  658.    indwrite = 0;
  659.    return b;
  660. }
  661.